package com.momoauth.common.core.filter;

import com.alibaba.fastjson2.JSON;
import lombok.extern.slf4j.Slf4j;

import javax.servlet.*;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;

@Slf4j
public class SqlFilter implements Filter {

    /**
     * 每当检测到SQL语句有注入的可能性时，立刻拒绝请求
     * TestSql语句：-1; delete  from  user; --
     */

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        Enumeration<String> params = servletRequest.getParameterNames();
        StringBuilder whereSql = new StringBuilder();
        while (params.hasMoreElements()) {
            String name = params.nextElement();
            String[] value = servletRequest.getParameterValues(name);
            for (String s : value) {
                whereSql.append(s);
            }
        }
        // 判断Sql语句是否存在注入的可能性
        if (sqlValidate(whereSql.toString())) {
            log.error("SQl注入语句：{}",whereSql);
            Map<String, Object> map = new HashMap<>();
            map.put("code", 40000);
            map.put("msg", "检测到非法参数，已拒绝请求。");
            handleCustomException(servletResponse, JSON.toJSONString(map));
            return ;
        }
        filterChain.doFilter(servletRequest,servletResponse);
    }

    /**
     * 匹配校验
     * @param str
     * @return
     */
    protected static boolean sqlValidate(String str) {
        str = str.toLowerCase();
        String badStr = "'| and | exec | execute | insert | select | delete | update | count | drop | chr | mid | master | truncate | char | declare | sitename | net user | xp_cmdshell | or | like | - | -- | + | , | like | // | / | % | #|insert |select |delete |update";
        String[] badStrs = badStr.split("\\|");
        for (String s : badStrs) {
            if (str.contains(s)) {
                return true;
            }
        }
        return false;
    }

    /**
     * 自定义错误返回信息
     * @param servletResponse
     * @param errorMsg
     */
    private void handleCustomException(ServletResponse servletResponse, String errorMsg) {
        servletResponse.setCharacterEncoding("UTF-8");
        servletResponse.setContentType("application/json;charset=UTF-8");
        try (PrintWriter writer = servletResponse.getWriter()) {
            writer.print(errorMsg);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
